package com.coscon.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.coscon.shiro.CustomFormAuthenticationFilter;
import com.coscon.shiro.CustomRolesAuthorizationFilter;
import com.coscon.shiro.MyShiroFilterFactoryBean;
import com.coscon.shiro.ShiroRealm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


/**
 * shiro配置
 * @author 409390047@qq.com
 * @Date: 2021/6/16 10:13
 */
@Configuration
@Slf4j
public class ShiroConfiguration {

    private final String cipherKey = "+a7dDBl+QSfPcT2qh2bc9g==";

    /**
     * 将自定义的验证方式加入容器
     * @return
     */
    @Bean
    public ShiroRealm shiroRealm() {
        ShiroRealm shiroRealm = new ShiroRealm();
        //shiroRealm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher());//配置密码重试多次自动锁定
        return shiroRealm;
    }
    
    /**
	     * ShiroFilterFactoryBean 处理拦截资源文件问题。
	     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的
	     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     */
    @Bean
    public MyShiroFilterFactoryBean shirFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
        MyShiroFilterFactoryBean shiroFilterFactoryBean = new MyShiroFilterFactoryBean();

        
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //登录的url
        shiroFilterFactoryBean.setLoginUrl("/login/index");
        // 未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/common/error/error403");
        //成功界面
        shiroFilterFactoryBean.setSuccessUrl("/jm/manager/home/index");
        
        /////////////////////////filters  自定义过滤器/////////////////////////
        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        filters.put("roleOrFilter", new CustomRolesAuthorizationFilter());//自定义的角色的or关系的filter
        //为什么不是@bean，而是new，因为有顺序问题，请参考https://www.cnblogs.com/gj1990/p/8057348.html
        filters.put("authc", new CustomFormAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filters);


        Map<String, String> filterMap = new HashMap<String, String>();

        //不需要认证
        filterMap.put("/**", "anon");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }
    
    
    /**
     * 
    * @Title: securityManager 
    * @Description: TODO(安全配置) 
    * @param @return    设定文件 
    * @return org.apache.shiro.mgt.SecurityManager    返回类型 
    * @throws
     */
    @Bean
    public org.apache.shiro.mgt.SecurityManager securityManagerByShrio() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
//        securityManager.setSessionManager(sessionManager());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }



//    @Bean
//    public DefaultWebSessionManager sessionManager() {
//        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
//        // 去掉shiro登录时url里的JSESSIONID
//        sessionManager.setSessionIdUrlRewritingEnabled(false);
//        return sessionManager;
//    }


    /**
     * 记住我
     */
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        cookieRememberMeManager.setCipherKey(Base64.decode(cipherKey));
        return cookieRememberMeManager;
    }
    /**
     * cookie 属性设置
     */
    public SimpleCookie rememberMeCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(604800 * 24 * 60 * 60);//7天
        return cookie;
    }


    /**
	     * 加入注解的使用，不加入这个注解不生效
	     *
	     * AuthorizationAttributeSourceAdvisor，shiro里实现的Advisor类，
	     * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aAsa = new AuthorizationAttributeSourceAdvisor();
        aAsa.setSecurityManager(securityManagerByShrio());
        return aAsa;
    }


    /**
     * 定义 DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator 与 AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor
     * 是为了让shiro的 注解生效 @RequiresRoles 与 @RequiresPermissions
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 配置Shiro生命周期处理器
     * @return
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }



    /*        *
            *在模板引擎中集成shiro权限标签
            * @author 409390047@qq.com
            * @date 2019/3/12
            * @param []
            * @return at.pollux.thymeleaf.shiro.dialect.ShiroDialect
        */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
    
}
